package singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author liouwb
 * 单例模式
 * 懒汉式 加锁(饿汉式加锁，效果一样)： 线程安全，可以被反射破坏
 */
public class SingletonLazyLockTest {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 懒汉式 加锁
        SingletonLazyLock lazyLock = SingletonLazyLock.getInstance();
        SingletonLazyLock lazyLock1 = SingletonLazyLock.getInstance();

        // 通过反射实例
        Class<SingletonLazyLock> lazyClass = SingletonLazyLock.class;
        Constructor<SingletonLazyLock> constructor = lazyClass.getDeclaredConstructor();

        constructor.setAccessible(true);
        SingletonLazyLock lazyLock2 = constructor.newInstance();

        // 验证单例是否全局只有一个实例
        System.out.println("正常获取的实例比较：" + (lazyLock == lazyLock1));
        // 反射获取与正常获取对比
        System.out.println("正常获取的实例比较：" + (lazyLock == lazyLock2));

        // 输出相应对象
        System.out.println("lazyLock ：" + lazyLock);
        System.out.println("lazyLock1：" + lazyLock1);
        System.out.println("lazyLock2：" + lazyLock2);

    }

    /**
     * 懒汉式 加锁
     */
    static class SingletonLazyLock {
        public static SingletonLazyLock instance;

        // 私有构造函数
        private SingletonLazyLock() {
            synchronized (SingletonLazyLock.class) {
                if (instance != null) {
                    throw new RuntimeException("不要用反射破坏单例");
                }
            }
        }

        public static synchronized SingletonLazyLock getInstance() {
            if (instance == null) {
                instance = new SingletonLazyLock();
            }

            return instance;
        }
    }
}
